package yyy.ab.modules.quartz;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;
import yyy.ab.common.core.ResultBean;
import yyy.ab.common.utils.StringUtils;
import yyy.ab.modules.quartz.entity.QuartzJobInfo;
import yyy.ab.modules.quartz.task.BaseJob;

/**
 * 定时任务工具类
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class QuartzJobManage {
    //
    private final Scheduler scheduler;

    /**
     * 添加任务
     *
     * @param quartzJobInfo quartz实体封装类
     * @return
     * @throws Exception
     */
    public ResultBean jobAdd(QuartzJobInfo quartzJobInfo) throws Exception {
        //检查传入参数
        ResultBean ResultBean = preTimerCheck(quartzJobInfo);
        if (!ResultBean.getSuccess()) return ResultBean;

        // 启动调度器
        scheduler.start();
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("jobTitle", quartzJobInfo.getJobTitle());
        jobDataMap.put("parameter", quartzJobInfo.getParameter());
        jobDataMap.put("description", quartzJobInfo.getDescription());
//        //构建job信息
//        JobDetail jobDetail = null;
//        try {
//            jobDetail = JobBuilder.newJob(getClass(quartzJobInfo.getJobClassName()).getClass()).withIdentity(quartzJobInfo.getJobName()).setJobData(jobDataMap).build();
//        } catch (ClassNotFoundException ex) {
//            return ResultBean.errorMsg("后台找不到该类名任务");
//        } catch (Exception ex) {
//            return ResultBean.errorMsg("构建Job信息失败，错误原因：" + ex.getMessage());
//        }

        try {
            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(quartzJobInfo.getJobClassName()).getClass()).withIdentity(quartzJobInfo.getJobName()).setJobData(jobDataMap).build();
            //表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJobInfo.getCronExpress());

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzJobInfo.getJobName())
                    .withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (ClassNotFoundException ex) {
            return ResultBean.errorMsg("后台找不到该类名任务");
        } catch (SchedulerException e) {
            log.error("创建定时任务失败" + e);
            return ResultBean.errorMsg("任务添加失败！错误信息：" + e.getMessage());
        } catch (Exception e) {
            if (e.getMessage().startsWith("CronExpression")) {
                return ResultBean.errorMsg("Cron表达式错误");
            } else {
                return ResultBean.errorMsg("后台找不到该类名任务");
            }
        }
        if (quartzJobInfo.getTriggerState() == null || "PAUSED".equalsIgnoreCase(quartzJobInfo.getTriggerState())) {
            //暂停任务
            scheduler.pauseJob(JobKey.jobKey(quartzJobInfo.getJobName()));
        }
        return ResultBean.success("任务添加成功！");
    }

    /**
     * @param triggerName
     * @param triggerGroupName
     * @param cronExpression
     * @Description: 修改一个任务的触发时间
     * @Title: QuartzManager.java
     */
    public ResultBean modifyJobTime(String triggerName, String triggerGroupName, String cronExpression) {
        try {
            if (StringUtils.isEmpty(triggerGroupName))
                triggerGroupName = QuartzJobEnum.TRIGGER_GROUP_NAME.getName();
            if (StringUtils.isEmpty(triggerName))
                triggerName = QuartzJobEnum.TRIGGER_NAME.getName();
            if (StringUtils.isEmpty(cronExpression))
                return ResultBean.errorMsg("cron时间表达式为空");
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                return ResultBean.errorMsg("没有对应的定时任务");
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cronExpression)) {
                //表达式调度构建器(即任务执行的时间)
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
                // 修改时间
                trigger.getTriggerBuilder().withSchedule(scheduleBuilder);
                // 重启触发器
                scheduler.resumeTrigger(triggerKey);
                return ResultBean.success("修改成功");
            }
            return ResultBean.errorMsg("当前新时间与之前设置的时间一致");
        } catch (Exception e) {
            return ResultBean.errorMsg("错误信息：" + e.getMessage());
        }
    }

    /**
     * 任务删除
     *
     * @param jobName
     * @param jobGroupName
     * @throws Exception
     */
    public ResultBean jobDelete(String jobName, String jobGroupName) throws Exception {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
            return ResultBean.success("任务删除成功！");
        } catch (Exception e) {
            return ResultBean.errorMsg("任务删除失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 任务暂停
     *
     * @param jobName
     * @param jobGroupName
     * @throws Exception
     */
    public ResultBean jobPause(String jobName, String jobGroupName) throws Exception {
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
            return ResultBean.success("任务暂停成功！");
        } catch (Exception e) {
            return ResultBean.errorMsg("任务暂停失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 任务继续
     *
     * @param jobName
     * @param jobGroupName
     * @throws Exception
     */
    public ResultBean jobResume(String jobName, String jobGroupName) throws Exception {
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
            return ResultBean.success("任务继续成功！");
        } catch (Exception e) {
            return ResultBean.errorMsg("任务继续失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 任务重启
     *
     * @param jobName
     * @param jobGroupName
     * @param cronExpression
     * @throws Exception
     */
    public ResultBean jobReschedule(String jobName, String jobGroupName, String cronExpression) throws Exception {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
            return ResultBean.success("任务重启成功！");
        } catch (SchedulerException e) {
            log.error("更新定时任务失败" + e);
            return ResultBean.errorMsg("任务重启失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 任务立即执行
     *
     * @param jobName
     * @param jobGroupName
     * @throws Exception
     */
    public ResultBean jobTrigger(String jobName, String jobGroupName) throws Exception {
        try {
            scheduler.triggerJob(JobKey.jobKey(jobName, jobGroupName));
            return ResultBean.success("任务立即执行成功！");
        } catch (SchedulerException e) {
            return ResultBean.errorMsg("任务立即执行失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 通过类名获取BaseJob子类
     *
     * @param classname
     * @return
     * @throws Exception
     */
    static BaseJob getClass(String classname) throws Exception {
        Class<?> cls = Class.forName(classname);
        return (BaseJob) cls.newInstance();
    }

    /**
     * 对quartzJobInfo封装实体类中的值进行非空检查
     *
     * @param quartzJobInfo
     * @return
     */
    private ResultBean preTimerCheck(QuartzJobInfo quartzJobInfo) {
        if (quartzJobInfo == null)
            return ResultBean.errorMsg("传入的对象quartzJobInfo为null");
        /****************************验证必须的参数是否为空start*****************************************/
        if (StringUtils.isEmpty(quartzJobInfo.getCronExpress()))
            return ResultBean.errorMsg("cron时间表达式为空");
        else if (StringUtils.isEmpty(quartzJobInfo.getJobClassName()))
            return ResultBean.errorMsg("需要执行的任务类名为空");
        /****************************验证必须的参数是否为空end*******************************************/

        /**************************验证非必须参数是否为空，如果为空给予默认值start**************************/
        if (StringUtils.isEmpty(quartzJobInfo.getJobName()))
            quartzJobInfo.setJobName(QuartzJobEnum.JOB_NAME.getName());
        if (StringUtils.isEmpty(quartzJobInfo.getJobGroupName()))
            quartzJobInfo.setJobGroupName(QuartzJobEnum.JOB_GROUP_NAME.getName());
        if (StringUtils.isEmpty(quartzJobInfo.getTriggerName()))
            quartzJobInfo.setTriggerName(QuartzJobEnum.TRIGGER_NAME.getName());
        if (StringUtils.isEmpty(quartzJobInfo.getTriggerGroupName()))
            quartzJobInfo.setTriggerGroupName(QuartzJobEnum.TRIGGER_GROUP_NAME.getName());
        /**************************验证非必须参数是否为空，如果为空给予默认值end****************************/

        return ResultBean.success();
    }
}
